from rest_framework import serializers
from book.models import HeroInfo, BookInfo


# 自定义序列化器类，完成序列化和反序列化的方法指定

class HeroInfoSerialiazer(serializers.Serializer):
    """
    英雄表序列化器
    """
    hname = serializers.CharField()
    hgender = serializers.IntegerField()
    hcomment = serializers.CharField()


class BookInfoSerializer(serializers.Serializer):
    """
    序列化器是对哪个模型类资源操作，定义名字时使用：该模型类名+Serializer

    """
    # 指定序列化字段返回字段---可以根据BookInfo模型类对应的字段类型指定
    # 反序列化验证时，可以指定选项参数进行验证
    btitle = serializers.CharField(max_length=20,min_length=2)
    # read_only的作用:只参与序列化过程，不参加反序列化（含验证流程）
    bpub_date = serializers.DateField(read_only=True)
    bread = serializers.IntegerField(max_value=200,min_value=10,default=0)
    # write_only=True 说明只参与反序列化，不参与序列化
    bcomment = serializers.IntegerField(write_only=True)
    is_delete = serializers.BooleanField(default=0)

    # 嵌套序列化返回   例如：返回图书信息时，将图书对应的英雄信息一并返回
    # 指定嵌套字段 主表嵌套附表，使用附表表名的小写_set
    # 返回的形式有三种，第一种返回关联表的id
    # heroinfo_set = serializers.PrimaryKeyRelatedField(many=True,queryset=HeroInfo.objects.all())
    # 2.第二种返回形式：返回关联表中str方法的结果
    # heroinfo_set = serializers.StringRelatedField(many=True)
    #3. 定义关联表的序列化进行指定
    # heroinfo_set = HeroInfoSerialiazer(many=True)

    # 验证图书的书名中不能有python
    # 方法验证：1.单一字段验证；2.多个字段验证
    def validate_btitle(self,attrs):
        """
        单一字段验证，书写形式validate_验证的字段
        :param attrs: 字段所对应的数据
        :return:
        """
        if attrs == "python":
            #验证后抛出异常：
            raise serializers.ValidationError('图书名中不能含有python')
        return attrs

    # 多个字段验证方法    阅读量大于评论量
    def validate(self, attrs):
        """

        :param attrs:接收所有的验证字段
        :return:
        """

        if attrs["bread"] > attrs["bcomment"]:
            # 验证不通过，抛出异常
            raise serializers.ValidationError('阅读量大于评论量')
        # 验证通过返回验证数据结果🔙
        return attrs

    #  保存方法
    def create(self, validated_data):
        """
        将保存数据库的业务，在该方法中封装
        :param validated_data: 接收验证后的数据
        :return:
        """
        book= BookInfo.objects.create(**validated_data)

        # 保存成功后，返回保存对象，方便下一步的序列化返回
        return book

    # 更新方法
    def update(self, instance, validated_data):
        """

        :param instance: 跟新的数据对象
        :param validated_data: 验证后的数据
        :return:
        """
        res = BookInfo.objects.filter(id=instance.id).update(**validated_data)
        if res == 0:
            raise serializers.ValidationError('跟新失败')
        book = BookInfo.objects.get(id=instance.id)

        return book
